constraint layout: Provide list models
authorMatthias Clasen <mclasen@redhat.com>
Tue, 2 Jul 2019 00:14:26 +0000 (20:14 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 2 Jul 2019 14:03:48 +0000 (10:03 -0400)
Provide list models for the constraints and guides,
so we can show them in the inspector, and use them
in e.g. the constraints editor.

docs/reference/gtk/gtk4-sections.txt
gtk/gtkconstraintlayout.c
gtk/gtkconstraintlayout.h

index ac9ea19fa93f21bcd0194cf8accc0b6f91dffb9f..6dc672ce8f4b0aa06fa346eadbe09f384c48974e 100644 (file)
@@ -7338,6 +7338,10 @@ gtk_constraint_layout_remove_guide
 gtk_constraint_layout_add_constraints_from_description
 gtk_constraint_layout_add_constraints_from_descriptionv
 
+<SUBSECTION>
+gtk_constraint_layout_observe_constraints
+gtk_constraint_layout_observe_guides
+
 <SUBSECTION Standard>
 GTK_TYPE_CONSTRAINT_LAYOUT
 gtk_constraint_layout_get_type
index 4623798b5e3136ba70fd6c91248ab699f4cd0f68..f23237e0d8f82733f7696fcff4672596acead939 100644 (file)
@@ -253,6 +253,9 @@ struct _GtkConstraintLayout
 
   /* HashSet<GtkConstraintGuide> */
   GHashTable *guides;
+
+  GListStore *constraints_observer;
+  GListStore *guides_observer;
 };
 
 G_DEFINE_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK_TYPE_LAYOUT_CHILD)
@@ -534,6 +537,19 @@ gtk_constraint_layout_finalize (GObject *gobject)
 {
   GtkConstraintLayout *self = GTK_CONSTRAINT_LAYOUT (gobject);
 
+  if (self->constraints_observer)
+    {
+      g_list_store_remove_all (self->constraints_observer);
+      g_object_remove_weak_pointer ((GObject *)self->constraints_observer,
+                                    (gpointer *)&self->constraints_observer);
+    }
+  if (self->guides_observer)
+    {
+      g_list_store_remove_all (self->guides_observer);
+      g_object_remove_weak_pointer ((GObject *)self->guides_observer,
+                                    (gpointer *)&self->guides_observer);
+    }
+
   g_clear_pointer (&self->bound_attributes, g_hash_table_unref);
   g_clear_pointer (&self->constraints, g_hash_table_unref);
   g_clear_pointer (&self->guides, g_hash_table_unref);
@@ -1709,10 +1725,32 @@ gtk_constraint_layout_add_constraint (GtkConstraintLayout *layout,
   layout_add_constraint (layout, constraint);
 
   g_hash_table_add (layout->constraints, constraint);
+  if (layout->constraints_observer)
+    g_list_store_append (layout->constraints_observer, constraint);
 
   gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
 }
 
+static void
+list_store_remove_item (GListStore *store,
+                        gpointer    item)
+{
+  int n_items;
+  int i;
+
+  n_items = g_list_model_get_n_items (G_LIST_MODEL (store));
+  for (i = 0; i < n_items; i++)
+    {
+      gpointer *model_item = g_list_model_get_item (G_LIST_MODEL (store), i);
+      g_object_unref (model_item);
+      if (item == model_item)
+        {
+          g_list_store_remove (store, i);
+          break;
+        }
+    }
+}
+
 /**
  * gtk_constraint_layout_remove_constraint:
  * @layout: a #GtkConstraintLayout
@@ -1731,6 +1769,8 @@ gtk_constraint_layout_remove_constraint (GtkConstraintLayout *layout,
 
   gtk_constraint_detach (constraint);
   g_hash_table_remove (layout->constraints, constraint);
+  if (layout->constraints_observer)
+    list_store_remove_item (layout->constraints_observer, constraint);
 
   gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
 }
@@ -1757,6 +1797,8 @@ gtk_constraint_layout_remove_all_constraints (GtkConstraintLayout *layout)
       gtk_constraint_detach (constraint);
       g_hash_table_iter_remove (&iter);
     }
+  if (layout->constraints_observer)
+    g_list_store_remove_all (layout->constraints_observer);
 
   gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
 }
@@ -1783,6 +1825,8 @@ gtk_constraint_layout_add_guide (GtkConstraintLayout *layout,
 
   gtk_constraint_guide_set_layout (guide, layout);
   g_hash_table_add (layout->guides, guide);
+  if (layout->guides_observer)
+    g_list_store_append (layout->guides_observer, guide);
 
   gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
 }
@@ -1807,6 +1851,8 @@ gtk_constraint_layout_remove_guide (GtkConstraintLayout *layout,
 
   gtk_constraint_guide_set_layout (guide, NULL);
   g_hash_table_remove (layout->guides, guide);
+  if (layout->guides_observer)
+    list_store_remove_item (layout->guides_observer, guide);
 
   gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
 }
@@ -2026,6 +2072,8 @@ gtk_constraint_layout_add_constraints_from_descriptionv (GtkConstraintLayout *la
 
           layout_add_constraint (layout, constraint);
           g_hash_table_add (layout->constraints, constraint);
+          if (layout->constraints_observer)
+            g_list_store_append (layout->constraints_observer, constraint);
 
           res = g_list_prepend (res, constraint);
         }
@@ -2116,3 +2164,83 @@ gtk_constraint_layout_add_constraints_from_description (GtkConstraintLayout *lay
 
   return res;
 }
+
+/**
+ * gtk_constraint_layout_observe_constraints:
+ * @layout: a #GtkConstraintLayout
+ * 
+ * Returns a #GListModel to track the constraints that are
+ * part of @layout.
+ * 
+ * Calling this function will enable extra internal bookkeeping
+ * to track constraints and emit signals on the returned listmodel.
+ * It may slow down operations a lot.
+ *
+ * Applications should try hard to avoid calling this function
+ * because of the slowdowns.
+ *
+ * Returns: (transfer full): a #GListModel tracking @layout's
+ *     constraints 
+ */
+GListModel *
+gtk_constraint_layout_observe_constraints (GtkConstraintLayout *layout)
+{
+  GHashTableIter iter;
+  gpointer key;
+
+  if (layout->constraints_observer)
+    return g_object_ref (G_LIST_MODEL (layout->constraints_observer));
+
+  layout->constraints_observer = g_list_store_new (GTK_TYPE_CONSTRAINT);
+  g_object_add_weak_pointer ((GObject *)layout->constraints_observer,
+                             (gpointer *)&layout->constraints_observer);
+
+  g_hash_table_iter_init (&iter, layout->constraints);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
+    {
+      GtkConstraint *constraint = key;
+      g_list_store_append (layout->constraints_observer, constraint);
+    }
+
+  return G_LIST_MODEL (layout->constraints_observer);
+}
+
+/**
+ * gtk_constraint_layout_observe_guides:
+ * @layout: a #GtkConstraintLayout
+ * 
+ * Returns a #GListModel to track the guides that are
+ * part of @layout.
+ * 
+ * Calling this function will enable extra internal bookkeeping
+ * to track guides and emit signals on the returned listmodel.
+ * It may slow down operations a lot.
+ *
+ * Applications should try hard to avoid calling this function
+ * because of the slowdowns.
+ *
+ * Returns: (transfer full): a #GListModel tracking @layout's
+ *     guides
+ */
+GListModel *
+gtk_constraint_layout_observe_guides (GtkConstraintLayout *layout)
+{
+  GHashTableIter iter;
+  gpointer key;
+
+  if (layout->guides_observer)
+    return g_object_ref (G_LIST_MODEL (layout->guides_observer));
+
+  layout->guides_observer = g_list_store_new (GTK_TYPE_CONSTRAINT_GUIDE);
+  g_object_add_weak_pointer ((GObject *)layout->guides_observer,
+                             (gpointer *)&layout->guides_observer);
+
+  g_hash_table_iter_init (&iter, layout->guides);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
+    {
+      GtkConstraintGuide *guide = key;
+      g_list_store_append (layout->guides_observer, guide);
+    }
+
+  return G_LIST_MODEL (layout->guides_observer);
+}
index 90d5e8492626a2ca09ab3e6e8f6502a67221a90c..fc7c6a468bc3a6bf934ab34f20f7e7782cb7b33a 100644 (file)
@@ -85,4 +85,9 @@ GList *                 gtk_constraint_layout_add_constraints_from_descriptionv
                                                                                  GHashTable          *views,
                                                                                  GError             **error);
 
+GDK_AVAILABLE_IN_ALL
+GListModel *          gtk_constraint_layout_observe_constraints (GtkConstraintLayout *layout);
+GDK_AVAILABLE_IN_ALL
+GListModel *          gtk_constraint_layout_observe_guides (GtkConstraintLayout *layout);
+
 G_END_DECLS